package me.sdevil507.org.controller;

import lombok.extern.slf4j.Slf4j;
import me.sdevil507.biz.common.exceptions.PhoneNumberExistedException;
import me.sdevil507.biz.common.exceptions.UserExistedException;
import me.sdevil507.biz.common.sms.captcha.enums.CaptchaType;
import me.sdevil507.biz.common.sms.captcha.service.CaptchaService;
import me.sdevil507.biz.screen.dto.ScreenSearchConditionDTO;
import me.sdevil507.org.dto.*;
import me.sdevil507.org.mapper.OrgInviteMapper;
import me.sdevil507.org.mapper.OrgUserMapper;
import me.sdevil507.org.po.OrgInvitePo;
import me.sdevil507.org.po.OrgPo;
import me.sdevil507.org.po.OrgUserPo;
import me.sdevil507.org.service.OrgExpertService;
import me.sdevil507.org.service.OrgInviteService;
import me.sdevil507.org.service.OrgService;
import me.sdevil507.org.service.OrgUserService;
import me.sdevil507.supports.jpa.PageConvertCallBack;
import me.sdevil507.supports.jpa.PageResultDTO;
import me.sdevil507.supports.jpa.PageResultGenerator;
import me.sdevil507.supports.result.ApiResultDTO;
import me.sdevil507.supports.result.ApiResultGenerator;
import me.sdevil507.supports.shiro.helper.OrgAccountHelper;
import me.sdevil507.supports.status.ApiStatusCode;
import me.sdevil507.supports.util.RegularExpressionUtil;
import me.sdevil507.systemAssist.Constant.SystemAssistConstant;
import me.sdevil507.systemAssist.systemLog.annotation.OperLog;
import org.apache.shiro.authz.annotation.RequiresPermissions;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.util.StringUtils;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;

import java.io.File;
import java.io.IOException;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;

/**
 * 组织机构下专家库
 *
 * @author sdevil507
 * created on 2020/8/7
 */
@RestController
@RequestMapping("/api/org/expert")
@Slf4j
public class OrgExpertController {

    @Autowired
    private OrgUserService orgUserService;

    @Autowired
    private OrgExpertService orgExpertService;

    @Autowired
    private OrgUserMapper orgUserMapper;

    @Autowired
    private OrgInviteService orgInviteService;

    @Autowired
    private OrgInviteMapper orgInviteMapper;

    @Autowired
    private CaptchaService captchaService;

    @Autowired
    private OrgService orgService;


    /**
     * 获取当前用户的权限下的智库
     *
     */
    public OrgUserMergeParamsDto setOrgIdList(OrgUserMergeParamsDto dto){
        Set<Long> orgIds = new HashSet<>();
        if(dto.getSearchDto().getOrgId() != null){
            orgIds.add(dto.getSearchDto().getOrgId());
        }else{
            orgIds = OrgAccountHelper.getOrgIdList();
        }
        dto.getSearchDto().setOrgIdList(orgIds);

        return dto;
    }

    /**
     * 分页获取机构下专家列表
     *
     * @param dto 入参参数
     * @return 分页数据
     */
    @SuppressWarnings("Convert2Lambda")
    @PostMapping("/readAllByPage")
    @RequiresPermissions("org:expert:view")
    public ApiResultDTO readAllExpertByPage(@RequestBody OrgUserMergeParamsDto dto) {
        this.setOrgIdList(dto);
        @SuppressWarnings("DuplicatedCode")
        Page<OrgUserPo> pagePos = orgUserService.readAllByPage(dto.getSearchDto(), dto.getPageDto(), dto.getSortDto());
        PageResultDTO<OrgUserResultDto> pageResultDto = PageResultGenerator.convert(pagePos, new PageConvertCallBack<OrgUserResultDto, OrgUserPo>() {
            @Override
            public List<OrgUserResultDto> exec(List<OrgUserPo> list) {
                return orgUserMapper.pos2dtos(list);
            }
        });
        // 执行是否全职专家标记
        for (OrgUserResultDto record : pageResultDto.getRecords()) {
            if (record.getExpertInfo() != null) {
                record.getExpertInfo().setFullTime(orgUserService.checkFullTime(record.getId(), dto.getSearchDto()));
                record.getExpertInfo().setLeader(orgUserService.checkLeader(record.getId(), dto.getSearchDto()));
            }
        }
        return ApiResultGenerator.create(ApiStatusCode.SUCCESS.getCode(), ApiStatusCode.SUCCESS.getDescription(), pageResultDto);
    }

    /**
     * 创建专家
     *
     * @return 专家创建
     */
    @OperLog(operTerminal = SystemAssistConstant.systemAssistTerminal.ORG, operClassify = SystemAssistConstant.systemAssistClassify.EXPERTDATABASE, operModule = SystemAssistConstant.systemAssistModule.EXPERT_ADD, operDesc = "")
    @PostMapping("/create")
    @RequiresPermissions("org:expert:add")
    public ApiResultDTO create(@RequestBody OrgUserParamsDto dto) {
        // 查询用户是否存在
        try {
            if(!StringUtils.isEmpty(dto.getRealName())){
                //过滤空格
                dto.setRealName(RegularExpressionUtil.filterSpace(dto.getRealName()));
            }
            orgExpertService.create(dto, OrgAccountHelper.getOrgId());
        } catch (PhoneNumberExistedException e) {
            return ApiResultGenerator.create(ApiStatusCode.EXPERT_EXISTED_IN.getCode(), ApiStatusCode.EXPERT_EXISTED_IN.getDescription());
        }
        return ApiResultGenerator.create(ApiStatusCode.SUCCESS.getCode(), ApiStatusCode.SUCCESS.getDescription(), dto);
    }

    /**
     * 更新专家信息
     *
     * @param dto 入参dto
     * @return 执行反馈
     */
    @OperLog(operTerminal = SystemAssistConstant.systemAssistTerminal.ORG, operClassify = SystemAssistConstant.systemAssistClassify.EXPERTDATABASE, operModule = SystemAssistConstant.systemAssistModule.EXPERT_UPDATE, operDesc = "")
    @PostMapping("/update")
    @RequiresPermissions("org:expert:edit")
    public ApiResultDTO update(@RequestBody OrgUserParamsDto dto) {
        try {
            if(!StringUtils.isEmpty(dto.getRealName())){
                dto.setRealName(RegularExpressionUtil.filterSpace(dto.getRealName()));
            }
            orgUserService.update(dto);
        } catch (PhoneNumberExistedException e) {
            return ApiResultGenerator.create(ApiStatusCode.ACCOUNT_EXISTED.getCode(), ApiStatusCode.ACCOUNT_EXISTED.getDescription());
        }
        return ApiResultGenerator.create(ApiStatusCode.SUCCESS.getCode(), ApiStatusCode.SUCCESS.getDescription(), dto);
    }

    /**
     * 删除专家信息
     *
     * @param dto 入参dto
     * @return 执行反馈
     */
    @OperLog(operTerminal = SystemAssistConstant.systemAssistTerminal.ORG, operClassify = SystemAssistConstant.systemAssistClassify.EXPERTDATABASE, operModule = SystemAssistConstant.systemAssistModule.EXPERT_DELETE, operDesc = "")
    @PostMapping("/delete")
    @RequiresPermissions("org:expert:delete")
    public ApiResultDTO delete(@RequestBody OrgUserParamsDto dto) {
        orgUserService.deleteExpertData(dto.getId());
        return ApiResultGenerator.create(ApiStatusCode.SUCCESS.getCode(), ApiStatusCode.SUCCESS.getDescription());
    }

    /**
     * 分页获取信息列表
     *
     * @param dto 聚合查询/分页/排序参数
     * @return 分页数据
     */
    @SuppressWarnings("Convert2Lambda")
    @PostMapping(value = "/readInvites")
    public ApiResultDTO readAllByPage(@RequestBody OrgInviteMergeParamsDto dto) {
        dto.getSearchDto().setOrgId(OrgAccountHelper.getOrgId());
        Page<OrgInvitePo> pagePos = orgInviteService.readAllByPage(dto.getSearchDto(), dto.getPageDto(), dto.getSortDto());
        PageResultDTO<OrgInviteResultDto> pageResultDto = PageResultGenerator.convert(pagePos, new PageConvertCallBack<OrgInviteResultDto, OrgInvitePo>() {
            @Override
            public List<OrgInviteResultDto> exec(List<OrgInvitePo> list) {
                return orgInviteMapper.pos2dtos(list);
            }
        });
        return ApiResultGenerator.create(ApiStatusCode.SUCCESS.getCode(), ApiStatusCode.SUCCESS.getDescription(), pageResultDto);
    }

    /**
     * 生成邀请链接
     *
     * @param dto 入参dto
     * @return 执行反馈
     */
    @PostMapping("/inviteUrl")
    public ApiResultDTO inviteUrl(@RequestBody OrgInviteParamsDto dto) {
        Long id = orgInviteService.inviteUrl(dto);
        return ApiResultGenerator.create(ApiStatusCode.SUCCESS.getCode(), ApiStatusCode.SUCCESS.getDescription(), id);
    }


    /**
     * 发送邀请短信
     *
     * @param dto 入参dto
     * @return 执行反馈
     */
    @OperLog(operTerminal = SystemAssistConstant.systemAssistTerminal.ORG, operClassify = SystemAssistConstant.systemAssistClassify.EXPERTDATABASE, operModule = SystemAssistConstant.systemAssistModule.EXPERT_INVITE, operDesc = "发送短信邀请专家")
    @PostMapping("/sendInviteMessage")
    @RequiresPermissions("org:expert:invite")
    public ApiResultDTO sendInviteMessage(@RequestBody OrgInviteParamsDto dto) {
        ApiResultDTO apiResultDTO;
        // 执行发送
        try {
            OrgPo orgPo = orgService.readOne(OrgAccountHelper.getOrgId());
            if (captchaService.sendInvatiMessage(dto.getPhoneNumber(), dto.getRealName(), orgPo.getNameZh(), dto.getInviteUrl(), dto.getInviteId())) {
                apiResultDTO = ApiResultGenerator.create(ApiStatusCode.SUCCESS.getCode(), ApiStatusCode.SUCCESS.getDescription());
            } else {
                apiResultDTO = ApiResultGenerator.create(ApiStatusCode.SEND_INVATE_MESSAGE_ERROR.getCode(), ApiStatusCode.SEND_INVATE_MESSAGE_ERROR.getDescription());
            }
        } catch (Exception e) {
            log.error("发送邀请短信:", e);
            apiResultDTO = ApiResultGenerator.create(ApiStatusCode.ERROR.getCode(), ApiStatusCode.ERROR.getDescription());
        }
        return apiResultDTO;
    }


    /**
     * 获取一条邀请记录信息
     *
     * @param dto 入参dto
     * @return 执行反馈
     */
    @PostMapping("/readInvite")
    public ApiResultDTO readInvite(@RequestBody OrgInviteParamsDto dto) {
        return ApiResultGenerator.create(ApiStatusCode.SUCCESS.getCode(), ApiStatusCode.SUCCESS.getDescription(), orgInviteService.readInvite(dto.getId()));
    }

    /**
     * 判断专家是否存在
     *
     * @param dto 入参dto
     * @return 执行反馈
     */
    @PostMapping("/existed")
    public ApiResultDTO existed(@RequestBody OrgUserParamsDto dto) {
        try {
            orgInviteService.existed(dto.getPhoneNumber());
        } catch (UserExistedException e) {
            return ApiResultGenerator.create(ApiStatusCode.EXPERT_EXISTED_IN.getCode(), ApiStatusCode.EXPERT_EXISTED_IN.getDescription());
        } catch (PhoneNumberExistedException e) {
            return ApiResultGenerator.create(ApiStatusCode.EXPERT_EXISTED.getCode(), ApiStatusCode.EXPERT_EXISTED.getDescription());
        }
        return ApiResultGenerator.create(ApiStatusCode.SUCCESS.getCode(), ApiStatusCode.SUCCESS.getDescription());
    }

    /**
     * 同意邀请
     *
     * @param dto 接受邀请入参
     * @return 执行反馈
     */
    @OperLog(operTerminal = SystemAssistConstant.systemAssistTerminal.ORG, operClassify = SystemAssistConstant.systemAssistClassify.EXPERTDATABASE, operModule = SystemAssistConstant.systemAssistModule.EXPERT_INVITE, operDesc = "专家接受邀请")
    @PostMapping("/inviteAgree")
    public ApiResultDTO inviteAgree(@RequestBody InviteAgreeDto dto) {
        if (!StringUtils.isEmpty(dto.getCode())) {
            // 注册入库流程
            // 1.判断是否反复注册
            if (orgUserService.existsByPhoneNumber(dto.getPhoneNumber())) {
                return ApiResultGenerator.create(ApiStatusCode.ACCOUNT_EXISTED.getCode(), ApiStatusCode.ACCOUNT_EXISTED.getDescription());
            }
            // 2.校验验证码
            boolean checkCaptchaState = captchaService.check(CaptchaType.REGISTER, dto.getPhoneNumber(), dto.getCode());
            if (!checkCaptchaState) {
                // 如果验证码校验失败
                return ApiResultGenerator.create(ApiStatusCode.CAPTCHA_INVALID.getCode(), ApiStatusCode.CAPTCHA_INVALID.getDescription());
            }
            // 3.执行注册
            orgInviteService.register(dto.getId());
        } else {
            // 绑定关系流程
            orgInviteService.bindOrg(dto.getId());
        }
        // 如果是从临时专家库中邀请的记录,需要执行删除
        orgInviteService.removeTemp(dto.getId());
        return ApiResultGenerator.create(ApiStatusCode.SUCCESS.getCode(), ApiStatusCode.SUCCESS.getDescription());
    }

    /**
     * 拒绝邀请
     *
     * @param dto 拒绝邀请入参
     * @return 执行反馈
     */
    @OperLog(operTerminal = SystemAssistConstant.systemAssistTerminal.ORG, operClassify = SystemAssistConstant.systemAssistClassify.EXPERTDATABASE, operModule = SystemAssistConstant.systemAssistModule.EXPERT_INVITE, operDesc = "专家拒绝邀请")
    @PostMapping("/inviteReject")
    public ApiResultDTO inviteReject(@RequestBody InviteRejectDto dto) {
        orgInviteService.reject(dto.getId());
        return ApiResultGenerator.create(ApiStatusCode.SUCCESS.getCode(), ApiStatusCode.SUCCESS.getDescription());
    }


    /**
     * @ClassName FruitOrgController
     * @Description : 导入专家数据
     *
     * @param file   excel文件
     * @Return : me.sdevil507.supports.result.ApiResultDTO
     * @Author : kzl
     * @Date : 2021年5月11日 11:16:59
     */
    @OperLog(operTerminal = SystemAssistConstant.systemAssistTerminal.ORG, operClassify = SystemAssistConstant.systemAssistClassify.EXPERTDATABASE, operModule = SystemAssistConstant.systemAssistModule.EXPERT_IMPORT, operDesc = "", recordRequestParams = false)
    @RequestMapping(value = "/importProject", method = RequestMethod.POST)
    @ResponseBody
    @RequiresPermissions("org:expert:import")
    public ApiResultDTO importProject(@RequestParam("file") MultipartFile file) {
        try {
            // 获取文件原始名称
            String originalFileName = file.getOriginalFilename();
            // 创建临时文件
            assert originalFileName != null;
            File tempFile = File.createTempFile("temp", originalFileName.substring(originalFileName.lastIndexOf(".")));
            // 将上传文件转为临时文件
            file.transferTo(tempFile);
            // 退出时删除临时文件
            tempFile.deleteOnExit();
            // 执行导入
            return orgExpertService.importExpertsByExcel(tempFile);
        } catch (IOException e) {
            log.error("导入成果数据失败:", e);
            return ApiResultGenerator.create("-1", "导入成果数据失败!");
        }
    }


    /**
     * 获取分析数据
     *
     * @return 分析数据
     */
    @PostMapping("/getAnalyze")
    public ApiResultDTO getAnalyze() {
        Map<String, Object> result = orgUserService.getAnalyze(OrgAccountHelper.getOrgId());
        return ApiResultGenerator.create(ApiStatusCode.SUCCESS.getCode(), ApiStatusCode.SUCCESS.getDescription(), result);
    }
}
